#ifndef COMBINAISON_HPP
#define COMBINAISON_HPP

/** Template qui permet d'obtenir les combinaisons de \f$n\f$ objects.
  *
  * Inspiré de "Combinations in C++" par Wong Shao Voon.
  *
  * A partir d'un ensemble d'entrée de \f$ n \f$ éléments, on en choisi
  * \f$ r \f$, tous distincts. Lorsqu'une nouvelle combinaison est trouvée, on
  * appelle une fonction responsable de traiter le résultat.
  *
  * Le but étant ici de récupérer les combinaisons dans une espèce de liste, la
  * fonction doit copier le résultat dans un conteneur.
  *
  * @author Johan "Solo" Luisier
  * @date Mai 2012
  *
  * @tparam BidIt paramètre de type "random access iterator", càd itérateur
  * bidirectionnel en entrée / sortie.
  *
  * @param[in] totDebut itérateur sur le début de la collection d'entrée.
  * @param[in] totFin itérateur sur la fin de la collection d'entrée.
  * @param[in] nbrTot nombre d'éléments dans la collection d'entrée
  * @param[in] combDebut itérateur sur le début de la combinaison de sortie.
  * @param[in] combFin itérateur sur la fin de la collection de sortie.
  * @param[in] combTot nombre d'éléments dans la collection de sortie.
  * @param[in] boucle
  * @param[in] fonc pointeur sur la fonction appelée lorsqu'une combinaison
  * est trouvée.
  * @param[in] ptr pointeur sur l'instance de classe qui utilise la méthode
  * @c fonc passée en argument.
  */
template < class BidIt, class Classe >
void combinaison( const BidIt &totDebut, const BidIt &totFin,
                  const unsigned &nbrTot,
                  const BidIt &combDebut, const BidIt &combFin,
                  const unsigned &combTot,
                  const unsigned& boucle,
                  void (Classe::*fonc)( const BidIt& debut, const BidIt& fin ),
                  Classe * ptr )
{
    unsigned r_size( combFin - combDebut );

    unsigned boucleLocal( boucle );
    unsigned nbrTotLocal( nbrTot );

    // Une nouvelle combinaison est détectée ici.
    if ( ( combTot + 1u ) > r_size )
    {
        (ptr ->*fonc)( combDebut, combFin );
        return;
    }
    //===========================

    unsigned i, cnt, cnt2;
    BidIt it1, it2;

    for ( i = 0u; i <= boucle; ++i )
    {
        it1 = combDebut;
        for ( cnt = 0u; cnt < combTot; ++cnt )
        {
            ++it1;
        }
        it2 = totDebut;
        for ( cnt2 = 0u; cnt2 < nbrTot + i; ++cnt2 )
        {
            ++it2;
        }

        *it1 = *it2;

        ++nbrTotLocal;

        combinaison( totDebut, totFin, nbrTotLocal,
                     combDebut, combFin, combTot + 1u, boucleLocal, fonc, ptr );

        --boucleLocal;
    }
};



#endif // COMBINAISON_HPP
